/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.lang.Nullable;
import org.springframework.util.StringValueResolver;

import java.beans.PropertyEditor;
import java.security.AccessControlContext;

/**
 * Configuration interface to be implemented by most bean factories. Provides
 * facilities to configure a bean factory, in addition to the bean factory
 * client methods in the {@link org.springframework.beans.factory.BeanFactory}
 * interface.
 *
 * <p>This bean factory interface is not meant to be used in normal application
 * code: Stick to {@link org.springframework.beans.factory.BeanFactory} or
 * {@link org.springframework.beans.factory.ListableBeanFactory} for typical
 * needs. This extended interface is just meant to allow for framework-internal
 * plug'n'play and for special access to bean factory configuration methods.
 *
 * 配置接口将被大部分的 bean 工厂实现。
 * 除了 BeanFactory 接口中的 bean 工厂客户端方法，还提供了配置一个 bean 工厂的功能。
 *
 * 这个 bean 工厂接口不是为了在正常的一个用代码中使用：
 * BeanFactory 和 ListableBeanFactory 满足经典的需求。
 * 本拓展接口只是为了
 * 	允许内部框架插件即插即用（plug'n'play）
 * 	以及 bean 工厂的配置方法特殊的访问
 *
 * @author Juergen Hoeller
 * @since 03.11.2003
 * @see org.springframework.beans.factory.BeanFactory
 * @see org.springframework.beans.factory.ListableBeanFactory
 * @see ConfigurableListableBeanFactory
 */
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

	/**
	 * Scope identifier for the standard singleton scope: "singleton".
	 * Custom scopes can be added via {@code registerScope}.
	 *
	 * 标准单例作用域的 作用域标识符（scope identifier）
	 * 可以通过 {@code registerScope} 添加自定义作用域
	 *
	 * @see #registerScope
	 */
	String SCOPE_SINGLETON = "singleton";

	/**
	 * Scope identifier for the standard prototype scope: "prototype".
	 * Custom scopes can be added via {@code registerScope}.
	 *
	 * 标准 原型 作用域的 作用域标识符
	 *
	 * @see #registerScope
	 */
	String SCOPE_PROTOTYPE = "prototype";


	/**
	 * Set the parent of this bean factory.
	 * <p>Note that the parent cannot be changed: It should only be set outside
	 * a constructor if it isn't available at the time of factory instantiation.
	 *
	 * 设置 bean 工厂的父工厂。
	 * 注意：该父工厂不能被改变：它只应该除构造方法外被设置，如果它在工厂实例化的时候不是可获得的。
	 *
	 * @param parentBeanFactory the parent BeanFactory
	 * @throws IllegalStateException if this factory is already associated with
	 * a parent BeanFactory
	 * @see #getParentBeanFactory()
	 */
	void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

	/**
	 * Set the class loader to use for loading bean classes.
	 * Default is the thread context class loader.
	 * <p>Note that this class loader will only apply to bean definitions
	 * that do not carry a resolved bean class yet. This is the case as of
	 * Spring 2.0 by default: Bean definitions only carry bean class names,
	 * to be resolved once the factory processes the bean definition.
	 *
	 * 设置 类加载器用于加载 bean 类。
	 * 默认值是线程上下文类加载器。
	 * 注意：这个类加载器只会应用到 尚未携带被解析的 bean 类的 bean 定义。
	 * Spring 2.0 以后默认情况下：bean 定义只会携带bean 类名称，一旦工厂处理了 bean 定义，
	 * 就会被解析。
	 *
	 * @param beanClassLoader the class loader to use,
	 * or {@code null} to suggest the default class loader
	 */
	void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);

	/**
	 * Return this factory's class loader for loading bean classes.
	 *
	 * 返回本工厂的加载 bean 类的类加载器
	 *
	 */
	@Nullable
	ClassLoader getBeanClassLoader();

	/**
	 * Specify a temporary ClassLoader to use for type matching purposes.
	 * Default is none, simply using the standard bean ClassLoader.
	 * <p>A temporary ClassLoader is usually just specified if
	 * <i>load-time weaving</i> is involved, to make sure that actual bean
	 * classes are loaded as lazily as possible. The temporary loader is
	 * then removed once the BeanFactory completes its bootstrap phase.
	 *
	 * 规定一个 出于类型匹配目的的 临时类加载器。
	 * 默认是空的，只是使用标准 bean 类加载器。
	 * 如果加载时编制（切面）被调用，一个临时的类加载器经常被规定去保证
	 * 实际的 bean 类尽可能地懒加载。
	 * 一旦本 BeanFactory 完成了它的启动阶段，该临时加载器就会被移除。
	 *
	 * @since 2.5
	 */
	void setTempClassLoader(@Nullable ClassLoader tempClassLoader);

	/**
	 * Return the temporary ClassLoader to use for type matching purposes,
	 * if any.
	 *
	 * 如果存在临时类加载器，返回该临时类加载器用于类型匹配。
	 *
	 * @since 2.5
	 */
	@Nullable
	ClassLoader getTempClassLoader();

	/**
	 * Set whether to cache bean metadata such as given bean definitions
	 * (in merged fashion) and resolved bean classes. Default is on.
	 * <p>Turn this flag off to enable hot-refreshing of bean definition objects
	 * and in particular bean classes. If this flag is off, any creation of a bean
	 * instance will re-query the bean class loader for newly resolved classes.
	 *
	 * 设置是否 缓存的 bean 元数据 比如 给定的定义（通过合并的方式），
	 * 并且解析 bean 类。默认是开启的。
	 * 把该标志关闭，就可以开启 bean 定义对象和具体的 bean 类的 热更新（hot-refreshing）。
	 * 如果标志位关闭，任何一个bean 实例的创建都会重新查询该 bean 类加载器中最新解析的类。
	 * 【标志位关闭--> bean 定义的热更新 + 会重新查询类加载器中最新解析的类】
	 *
	 */
	void setCacheBeanMetadata(boolean cacheBeanMetadata);

	/**
	 * Return whether to cache bean metadata such as given bean definitions
	 * (in merged fashion) and resolved bean classes.
	 *
	 * 返回标志位
	 *
	 */
	boolean isCacheBeanMetadata();

	/**
	 * Specify the resolution strategy for expressions in bean definition values.
	 * <p>There is no expression support active in a BeanFactory by default.
	 * An ApplicationContext will typically set a standard expression strategy
	 * here, supporting "#{...}" expressions in a Unified EL compatible style.
	 *
	 * 规定 bean 定义的值中的表达式 解析策略。
	 * 默认情况下，BeanFactory 中没有激活的表达式支持。
	 * 一个应用上下文会通过这个方法，典型地设置一个标准的表达式策略，
	 * 支持类似 #{...} 的表达式 的统一的 EL 兼容的风格。
	 *
	 * （：设置 Spring el 表达式解析器）
	 *
	 * @since 3.0
	 */
	void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);

	/**
	 * Return the resolution strategy for expressions in bean definition values.
	 * @since 3.0
	 */
	@Nullable
	BeanExpressionResolver getBeanExpressionResolver();

	/**
	 * Specify a Spring 3.0 ConversionService to use for converting
	 * property values, as an alternative to JavaBeans PropertyEditors.
	 *
	 * 指定一个 Spring 3.0 的转换服务 用于转换属性值，
	 * 作为 JavaBeans PropertyEditors 的替代方案。
	 * （：ConversionService  类型转换）
	 *
	 * @since 3.0
	 */
	void setConversionService(@Nullable ConversionService conversionService);

	/**
	 * Return the associated ConversionService, if any.
	 * @since 3.0
	 */
	@Nullable
	ConversionService getConversionService();

	/**
	 * Add a PropertyEditorRegistrar to be applied to all bean creation processes.
	 * <p>Such a registrar creates new PropertyEditor instances and registers them
	 * on the given registry, fresh for each bean creation attempt. This avoids
	 * the need for synchronization on custom editors; hence, it is generally
	 * preferable to use this method instead of {@link #registerCustomEditor}.
	 *
	 * 添加一个 属性编辑注册器 应用到所有 bean 创建的处理过程中。
	 * 这样一个注册器作用是：
	 * 	1.创建一个新的 属性编辑器实例；
	 * 	2.把 属性编辑器实例注册到给定的注册器上；
	 * 	3.每次bean 创建尝试都是新的。
	 * 这样就避免了在自定义编辑器上进行同步的需要。因此，通常使用这个方法比
	 * registerCustomEditor 方法 更合适（preferable）。
	 * （：PropertyEditor 类型转换）
	 *
	 * @param registrar the PropertyEditorRegistrar to register
	 */
	void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);

	/**
	 * Register the given custom property editor for all properties of the
	 * given type. To be invoked during factory configuration.
	 * <p>Note that this method will register a shared custom editor instance;
	 * access to that instance will be synchronized for thread-safety. It is
	 * generally preferable to use {@link #addPropertyEditorRegistrar} instead
	 * of this method, to avoid for the need for synchronization on custom editors.
	 *
	 * 根据给定的类型的所有属性，注册给定的自定义属性编辑器。
	 * 在工厂配置时被调用。
	 * 注意：这个方法会注册一个共享的自定义编辑器实例；
	 * 关于该实例的访问将会是同步的，线程安全的。
	 * 使用上面的方法代替本方法，是为了避免 在自定义编辑器上进行同步的需要。
	 *
	 * @param requiredType type of the property
	 * @param propertyEditorClass the {@link PropertyEditor} class to register
	 */
	void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);

	/**
	 * Initialize the given PropertyEditorRegistry with the custom editors
	 * that have been registered with this BeanFactory.
	 *
	 * 使用 本 BeanFactory 注册的自定义编辑器来 初始化传参中的 属性编辑注册器。
	 *
	 * @param registry the PropertyEditorRegistry to initialize
	 */
	void copyRegisteredEditorsTo(PropertyEditorRegistry registry);

	/**
	 * Set a custom type converter that this BeanFactory should use for converting
	 * bean property values, constructor argument values, etc.
	 * <p>This will override the default PropertyEditor mechanism and hence make
	 * any custom editors or custom editor registrars irrelevant.
	 *
	 * 设置一个自定义类型转换器以供
	 * 本 BeanFactory 转换 bean 属性值以及 构造方法中的参数值，等等。
	 * 这个方法会重写默认的 属性编辑器机制，因此会导致任何自定义编辑器或者自定义编辑器的注册器无效。
	 *
	 * @see #addPropertyEditorRegistrar
	 * @see #registerCustomEditor
	 * @since 2.5
	 */
	void setTypeConverter(TypeConverter typeConverter);

	/**
	 * Obtain a type converter as used by this BeanFactory. This may be a fresh
	 * instance for each call, since TypeConverters are usually <i>not</i> thread-safe.
	 * <p>If the default PropertyEditor mechanism is active, the returned
	 * TypeConverter will be aware of all custom editors that have been registered.
	 * @since 2.5
	 */
	TypeConverter getTypeConverter();

	/**
	 * Add a String resolver for embedded values such as annotation attributes.
	 *
	 * 添加一个 嵌入值（比如 注解的属性）字符串解析器
	 *
	 * @param valueResolver the String resolver to apply to embedded values
	 * @since 3.0
	 */
	void addEmbeddedValueResolver(StringValueResolver valueResolver);

	/**
	 * Determine whether an embedded value resolver has been registered with this
	 * bean factory, to be applied through {@link #resolveEmbeddedValue(String)}.
	 *
	 * 确定 一个 嵌入值解析器（embedded value resolver）是否被注册到 本 bean　工厂。
	 * 通过 resolveEmbeddedValue(String) 方法进行应用。
	 *
	 * @since 4.3
	 */
	boolean hasEmbeddedValueResolver();

	/**
	 * Resolve the given embedded value, e.g. an annotation attribute.
	 *
	 * 解析给定的嵌套值，比如一个注解的属性。
	 *
	 * @param value the value to resolve
	 * @return the resolved value (may be the original value as-is)
	 * @since 3.0
	 */
	@Nullable
	String resolveEmbeddedValue(String value);

	/**
	 * Add a new BeanPostProcessor that will get applied to beans created
	 * by this factory. To be invoked during factory configuration.
	 * <p>Note: Post-processors submitted here will be applied in the order of
	 * registration; any ordering semantics expressed through implementing the
	 * {@link org.springframework.core.Ordered} interface will be ignored. Note
	 * that autodetected post-processors (e.g. as beans in an ApplicationContext)
	 * will always be applied after programmatically registered ones.
	 *
	 * 添加一个新的 BeanPostProcessor ，它会被本工厂应用到创建bean 的过程中。
	 * 在工厂配置过程中被调用。
	 * 注意：本方法提交后置处理器，会被按照注册的顺序被应用。
	 * 【任何通过 Ordered 接口实现的排序语义表达式都将会被忽略。】
	 * 注意：自动检测到的后置处理器（比如：应用上下文中作为 beans 的）总是会在
	 * 以编程方式注册的后置处理器 之后应用。
	 * 【自动检测的后置处理器比 编程确定的 顺序靠后】
	 *
	 * @param beanPostProcessor the post-processor to register
	 */
	void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

	/**
	 * Return the current number of registered BeanPostProcessors, if any.
	 */
	int getBeanPostProcessorCount();

	/**
	 * Register the given scope, backed by the given Scope implementation.
	 *
	 * 注册给定的作用域，由给定的作用域的实现 支持。
	 *
	 * @param scopeName the scope identifier
	 * @param scope the backing Scope implementation
	 */
	void registerScope(String scopeName, Scope scope);

	/**
	 * Return the names of all currently registered scopes.
	 * <p>This will only return the names of explicitly registered scopes.
	 * Built-in scopes such as "singleton" and "prototype" won't be exposed.
	 *
	 * 返回所有当前注册的作用域名称。
	 * 本方法只会返回显示注册的作用域的名称。
	 * 内建的作用域比如 singleton prototype 都不会暴露。
	 *
	 * @return the array of scope names, or an empty array if none
	 * @see #registerScope
	 */
	String[] getRegisteredScopeNames();

	/**
	 * Return the Scope implementation for the given scope name, if any.
	 * <p>This will only return explicitly registered scopes.
	 * Built-in scopes such as "singleton" and "prototype" won't be exposed.
	 * @param scopeName the name of the scope
	 * @return the registered Scope implementation, or {@code null} if none
	 * @see #registerScope
	 */
	@Nullable
	Scope getRegisteredScope(String scopeName);

	/**
	 * Provides a security access control context relevant to this factory.
	 *
	 * 提供一个 安全的 跟本工厂相关的 访问控制上下文。
	 *
	 * @return the applicable AccessControlContext (never {@code null})
	 * @since 3.0
	 */
	AccessControlContext getAccessControlContext();

	/**
	 * Copy all relevant configuration from the given other factory.
	 * <p>Should include all standard configuration settings as well as
	 * BeanPostProcessors, Scopes, and factory-specific internal settings.
	 * Should not include any metadata of actual bean definitions,
	 * such as BeanDefinition objects and bean name aliases.
	 *
	 * 从给定的其他工厂 拷贝所有的相关配置。
	 * 应该包括
	 * 	1.所有的标准的配置设置 以及
	 * 	2.BeanPostProcessors
	 * 	3.作用域
	 * 	4.具体工厂内部配置
	 *
	 * 不应该抱愧任何实际 bean 定义的元数据，比如 BeanDefinition 对象和 bean 名称别名。
	 *
	 * @param otherFactory the other BeanFactory to copy from
	 */
	void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);

	/**
	 * Given a bean name, create an alias. We typically use this method to
	 * support names that are illegal within XML ids (used for bean names).
	 * <p>Typically invoked during factory configuration, but can also be
	 * used for runtime registration of aliases. Therefore, a factory
	 * implementation should synchronize alias access.
	 *
	 * 给定一个 bean 名称，创建一个别名。
	 * 我们通常会使用这个方法支持 XML id 标签中不合法的名称（作为 bean 名称使用）。
	 * 通常，工厂配置期间进行调用，但是也可以用来别名的运行时注册。
	 * 因此，一个工厂的实现应该同步别名的访问。
	 *
	 * @param beanName the canonical name of the target bean
	 * @param alias the alias to be registered for the bean
	 * @throws BeanDefinitionStoreException if the alias is already in use
	 */
	void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;

	/**
	 * Resolve all alias target names and aliases registered in this
	 * factory, applying the given StringValueResolver to them.
	 * <p>The value resolver may for example resolve placeholders
	 * in target bean names and even in alias names.
	 *
	 * 解析所有的别名目标名称 以及 注册在本工厂的别名。
	 * 向他们提供给定的 StringValueResolver
	 * 传入的 值解析器，比如可以解析在目标 bean 名称中甚至 别名中的占位符。
	 * 【StringValueResolver 解析占位符】
	 *
	 * @param valueResolver the StringValueResolver to apply
	 * @since 2.5
	 */
	void resolveAliases(StringValueResolver valueResolver);

	/**
	 * Return a merged BeanDefinition for the given bean name,
	 * merging a child bean definition with its parent if necessary.
	 * Considers bean definitions in ancestor factories as well.
	 *
	 * 根据给定的名称返回一个合并后的 BeanDefinition
	 * 如果有必要，将子 bean definition 和 它的父 bean definition 进行合并。
	 * 同时考虑祖先工厂中的 bean 定义。
	 * 【关于子 bean definition ：查了一下，感觉类似继承的结构。bean 可以配置 parent 属性，相当于 extends】
	 *
	 * @param beanName the name of the bean to retrieve the merged definition for
	 * @return a (potentially merged) BeanDefinition for the given bean
	 * @throws NoSuchBeanDefinitionException if there is no bean definition with the given name
	 * @since 2.5
	 */
	BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	/**
	 * Determine whether the bean with the given name is a FactoryBean.
	 *
	 * 确定 给定名称的 bean 是否一个 FactoryBean
	 *
	 * @param name the name of the bean to check
	 * @return whether the bean is a FactoryBean
	 * ({@code false} means the bean exists but is not a FactoryBean)
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @since 2.5
	 */
	boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;

	/**
	 * Explicitly control the current in-creation status of the specified bean.
	 * For container-internal use only.
	 *
	 * 显式控制 具体的 bean 的当前在创建中的状态。
	 * 仅供容器内部使用。
	 *
	 * @param beanName the name of the bean
	 * @param inCreation whether the bean is currently in creation
	 * @since 3.1
	 */
	void setCurrentlyInCreation(String beanName, boolean inCreation);

	/**
	 * Determine whether the specified bean is currently in creation.
	 *
	 * 确定 具体的bean 是否在创建过程中。
	 *
	 * @param beanName the name of the bean
	 * @return whether the bean is currently in creation
	 * @since 2.5
	 */
	boolean isCurrentlyInCreation(String beanName);

	/**
	 * Register a dependent bean for the given bean,
	 * to be destroyed before the given bean is destroyed.
	 *
	 * 根据给定的 bean 注册一个独立的 bean，在给定的 bean 毁灭之前该独立的 bean 会被毁灭。
	 * 【bean　之间的依赖】
	 *
	 * @param beanName the name of the bean
	 * @param dependentBeanName the name of the dependent bean
	 * @since 2.5
	 */
	void registerDependentBean(String beanName, String dependentBeanName);

	/**
	 * Return the names of all beans which depend on the specified bean, if any.
	 *
	 * 如果有的话，返回所有依赖具体的 bean 的所有 bean 的名称。
	 * 【bean　之间的依赖】
	 *
	 * @param beanName the name of the bean
	 * @return the array of dependent bean names, or an empty array if none
	 * @since 2.5
	 */
	String[] getDependentBeans(String beanName);

	/**
	 * Return the names of all beans that the specified bean depends on, if any.
	 *
	 * 如果有的话，返回给定的 bean 依赖着的所有 bean 的名称。
	 * 【bean　之间的依赖】
	 * 【跟上面的反向操作】
	 *
	 * @param beanName the name of the bean
	 * @return the array of names of beans which the bean depends on,
	 * or an empty array if none
	 * @since 2.5
	 */
	String[] getDependenciesForBean(String beanName);

	/**
	 * Destroy the given bean instance (usually a prototype instance
	 * obtained from this factory) according to its bean definition.
	 * <p>Any exception that arises during destruction should be caught
	 * and logged instead of propagated to the caller of this method.
	 *
	 * 摧毁给定的根据它的 bean 定义得到的 bean 实例（通常是一个在本工厂中获得的非单例的实例）
	 * （异常捕捉并日志记录而非传给调用方法）
	 *
	 * @param beanName the name of the bean definition
	 * @param beanInstance the bean instance to destroy
	 */
	void destroyBean(String beanName, Object beanInstance);

	/**
	 * Destroy the specified scoped bean in the current target scope, if any.
	 * <p>Any exception that arises during destruction should be caught
	 * and logged instead of propagated to the caller of this method.
	 *
	 * 如果有的话，摧毁当前目标作用域中的具体的作用域中的 bean
	 * （异常捕捉并日志记录而非传给调用方法）
	 *
	 * @param beanName the name of the scoped bean
	 */
	void destroyScopedBean(String beanName);

	/**
	 * Destroy all singleton beans in this factory, including inner beans that have
	 * been registered as disposable. To be called on shutdown of a factory.
	 * <p>Any exception that arises during destruction should be caught
	 * and logged instead of propagated to the caller of this method.
	 *
	 * 摧毁本工厂中所有的单例 bean，包括内部已经注册为可以丢弃的 bean。
	 * 一个工厂关闭的时候将被调用。
	 *（异常捕捉并日志记录而非传给调用方法）
	 *
	 */
	void destroySingletons();

}
